home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / sys5 / iscwmpst.z / iscwmpst / tcp / util / bridge.c next >
Encoding:
C/C++ Source or Header  |  1991-10-29  |  5.2 KB  |  222 lines

  1. static char  rcsid[] = "@(#) $Header: bridge.c,v 1.9 91/10/25 14:21:25 deyke Exp $";
  2.  
  3. #define _HPUX_SOURCE
  4.  
  5. #include <sys/types.h>
  6.  
  7. #include <signal.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <sys/socket.h>
  12. #include <time.h>
  13. #include <unistd.h>
  14.  
  15. #ifdef __STDC__
  16. #define __ARGS(x)       x
  17. #else
  18. #define __ARGS(x)       ()
  19. #define const
  20. #endif
  21.  
  22. struct sockaddr *build_sockaddr __ARGS((char *name, int *addrlen));
  23.  
  24. /* SLIP constants */
  25.  
  26. #define FR_END          0300    /* Frame End */
  27. #define FR_ESC          0333    /* Frame Escape */
  28. #define T_FR_END        0334    /* Transposed frame end */
  29. #define T_FR_ESC        0335    /* Transposed frame escape */
  30.  
  31. /* KISS constants */
  32.  
  33. #define KISS_DATA       0
  34.  
  35. /* AX25 constants */
  36.  
  37. #define AXALEN          7       /* Total AX.25 address length, including SSID */
  38. #define E               0x01    /* Address extension bit */
  39. #define REPEATED        0x80    /* Has-been-repeated bit in repeater field */
  40. #define SSID            0x1e    /* Sub station ID */
  41.  
  42. #define uchar(c)        ((unsigned char) (c))
  43.  
  44. struct conn {
  45.   struct conn *prev, *next;
  46.   char  call[AXALEN];
  47.   int  fd;
  48.   int  mask;
  49.   unsigned int  cnt;
  50.   char  buf[4096];
  51. };
  52.  
  53. /* AX.25 broadcast address: "QST-0" in shifted ascii */
  54. static char  ax25_bdcst[] = {
  55.   'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, ('0' << 1) | E,
  56. };
  57.  
  58. /* NET/ROM broadcast address: "NODES-0" in shifted ascii */
  59. static char  nr_bdcst[] = {
  60.   'N' << 1, 'O' << 1, 'D' << 1, 'E' << 1, 'S' << 1, ' ' << 1, ('0' << 1) | E
  61. };
  62.  
  63. static int  filemask;
  64. static struct conn *connections;
  65.  
  66. static void sigpipe_handler __ARGS((int sig, int code, struct sigcontext *scp));
  67. static void create_conn __ARGS((int flisten));
  68. static void close_conn __ARGS((struct conn *p));
  69. static int addreq __ARGS((char *a, char *b));
  70. static void route_packet __ARGS((struct conn *p));
  71.  
  72. /*---------------------------------------------------------------------------*/
  73.  
  74. static void sigpipe_handler(sig, code, scp)
  75. int  sig, code;
  76. struct sigcontext *scp;
  77. {
  78.   scp->sc_syscall_action = SIG_RETURN;
  79. }
  80.  
  81. /*---------------------------------------------------------------------------*/
  82.  
  83. static void create_conn(flisten)
  84. int  flisten;
  85. {
  86.  
  87.   int  fd, addrlen;
  88.   struct conn *p;
  89.   struct sockaddr addr;
  90.  
  91.   addrlen = 0;
  92.   fd = accept(flisten, &addr, &addrlen);
  93.   if (fd >= 0) {
  94.     p = (struct conn *) calloc(1, sizeof(struct conn ));
  95.     p->fd = fd;
  96.     p->mask = (1 << p->fd);
  97.     filemask |= p->mask;
  98.     if (connections) {
  99.       p->next = connections;
  100.       connections->prev = p;
  101.     }
  102.     connections = p;
  103.   }
  104. }
  105.  
  106. /*---------------------------------------------------------------------------*/
  107.  
  108. static void close_conn(p)
  109. struct conn *p;
  110. {
  111.   close(p->fd);
  112.   filemask &= ~p->mask;
  113.   if (p->prev) p->prev->next = p->next;
  114.   if (p->next) p->next->prev = p->prev;
  115.   if (p == connections) connections = p->next;
  116.   free(p);
  117. }
  118.  
  119. /*---------------------------------------------------------------------------*/
  120.  
  121. static int  addreq(a, b)
  122. register char  *a, *b;
  123. {
  124.   if (*a++ != *b++) return 0;
  125.   if (*a++ != *b++) return 0;
  126.   if (*a++ != *b++) return 0;
  127.   if (*a++ != *b++) return 0;
  128.   if (*a++ != *b++) return 0;
  129.   if (*a++ != *b++) return 0;
  130.   return (*a & SSID) == (*b & SSID);
  131. }
  132.  
  133. /*---------------------------------------------------------------------------*/
  134.  
  135. static void route_packet(p)
  136. struct conn *p;
  137. {
  138.  
  139.   char  *ap;
  140.   char  *dest;
  141.   char  *src;
  142.   int  multicast;
  143.   struct conn *p1, *p1next;
  144.  
  145.   if ((*p->buf & 0xf) != KISS_DATA) return;
  146.   dest = p->buf + 1;
  147.   ap = src = dest + AXALEN;
  148.   while (!(ap[6] & E)) {
  149.     ap += AXALEN;
  150.     if (ap[6] & REPEATED)
  151.       src = ap;
  152.     else {
  153.       dest = ap;
  154.       break;
  155.     }
  156.   }
  157.   memcpy(p->call, src, AXALEN);
  158.   multicast = (addreq(dest, ax25_bdcst) || addreq(dest, nr_bdcst));
  159.   for (p1 = connections; p1; p1 = p1next) {
  160.     p1next = p1->next;
  161.     if (p1 != p && (multicast || !*p1->call || addreq(dest, p1->call))) {
  162.       if (write(p1->fd, p->buf, p->cnt) <= 0) close_conn(p1);
  163.     }
  164.   }
  165. }
  166.  
  167. /*---------------------------------------------------------------------------*/
  168.  
  169. int main()
  170. {
  171.  
  172.   char buf[1024];
  173.   int addrlen;
  174.   int arg;
  175.   int flisten, flistenmask;
  176.   int i;
  177.   int n;
  178.   int readmask;
  179.   struct conn *p;
  180.   struct sigvec vec;
  181.   struct sockaddr *addr;
  182.  
  183.   for (n = 0; n < _NFILE; n++) close(n);
  184.   chdir("/");
  185.   setpgrp();
  186.  
  187.   vec.sv_mask = vec.sv_flags = 0;
  188.   vec.sv_handler = sigpipe_handler;
  189.   sigvector(SIGPIPE, &vec, (struct sigvec *) 0);
  190.  
  191.   addr = build_sockaddr("*:4713", &addrlen);
  192.   if (!addr) exit(1);
  193.   flisten = socket(addr->sa_family, SOCK_STREAM, 0);
  194.   if (flisten < 0) exit(1);
  195.   arg = 1;
  196.   setsockopt(flisten, SOL_SOCKET, SO_REUSEADDR, (char *) &arg, sizeof(arg));
  197.   if (bind(flisten, addr, addrlen)) exit(1);
  198.   if (listen(flisten, SOMAXCONN)) exit(1);
  199.   filemask = flistenmask = (1 << flisten);
  200.  
  201.   for (; ; ) {
  202.     readmask = filemask;
  203.     if (select(32, &readmask, (int *) 0, (int *) 0, (struct timeval *) 0) <= 0)
  204.       continue;
  205.     if (readmask & flistenmask) create_conn(flisten);
  206.     for (p = connections; p; p = p->next)
  207.       if (readmask & p->mask) {
  208.     n = read(p->fd, buf, sizeof(buf));
  209.     if (n <= 0) {
  210.       close_conn(p);
  211.       break;
  212.     }
  213.     for (i = 0; i < n; i++)
  214.       if (uchar(p->buf[p->cnt++] = buf[i]) == FR_END) {
  215.         if (p->cnt > 1) route_packet(p);
  216.         p->cnt = 0;
  217.       }
  218.       }
  219.   }
  220. }
  221.  
  222.